/*
 * Copyright 2011 J. Auer, J. Andert, F.-J. Jendrusch, U. Celebi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.fuberlin.replication.application.android.communication.bluetooth;

import java.util.Set;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import de.fuberlin.replication.R;

/**
 * Bluetooth device list activity.
 */
public class BluetoothDeviceListActivity extends Activity {
	/** Activity result intent extra name for the selected Bluetooth device address. */
	public static final String EXTRA_DEVICE_ADDRESS = "de.fuberlin.replication.application.android.communication.bluetooth.EXTRA_DEVICE_ADDRESS";

	/** Bluetooth adapter (default). */
	BluetoothAdapter adapter;

	/** Paired Bluetooth devices title. */
	TextView pairedDevicesTitle;

	/** Paired Bluetooth devices list. */
	ListView pairedDevices;

	/** Paired Bluetooth devices list adapter. */
	ArrayAdapter<String> pairedDevicesArrayAdapter;

	/** Other Bluetooth devices title. */
	TextView otherDevicesTitle;

	/** Other Bluetooth devices list. */
	ListView otherDevices;

	/** Other Bluetooth devices list adapter. */
	ArrayAdapter<String> otherDevicesArrayAdapter;

	/** Bluetooth scan button. */
	Button scan;

	/** Bluetooth discoverable button. */
	Button discoverable;

	private final ListView.OnItemClickListener deviceOnClickListener = new ListView.OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
			if (adapter.isDiscovering())
				adapter.cancelDiscovery();

			String text = ((TextView) v).getText().toString();
			String address = text.substring(text.length() - 17);

			Intent intent = new Intent();
			intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

			setResult(Activity.RESULT_OK, intent);

			finish();
		}
	};

	private final View.OnClickListener scanOnClickListener = new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			scan.setClickable(false);
			scan.setText(R.string.bluetooth_button_scanning);

			setProgressBarIndeterminateVisibility(true);

			otherDevicesArrayAdapter.clear();

			if (adapter.isDiscovering())
				adapter.cancelDiscovery();

			adapter.startDiscovery();
		}
	};

	private final View.OnClickListener discoverableOnClickListener = new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			if (adapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
				Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
				discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 60);

				startActivity(discoverableIntent);
			}
		}
	};

	private final BroadcastReceiver receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();

			if (action.equals(BluetoothDevice.ACTION_FOUND)) {
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

				if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
					otherDevicesTitle.setVisibility(View.VISIBLE);
					otherDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
				}
			} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
				setProgressBarIndeterminateVisibility(false);

				scan.setText(R.string.bluetooth_button_scan);
				scan.setClickable(true);

				if (otherDevicesArrayAdapter.getCount() == 0)
					otherDevicesTitle.setVisibility(View.GONE);
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setResult(Activity.RESULT_CANCELED);

		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		setContentView(R.layout.bluetooth_device_list);

		pairedDevicesTitle = (TextView) findViewById(R.id.bluetooth_paired_devices_title);
		pairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.bluetooth_device_name);

		pairedDevices = (ListView) findViewById(R.id.bluetooth_paired_devices);
		pairedDevices.setAdapter(pairedDevicesArrayAdapter);
		pairedDevices.setOnItemClickListener(deviceOnClickListener);

		otherDevicesTitle = (TextView) findViewById(R.id.bluetooth_other_devices_title);
		otherDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.bluetooth_device_name);

		otherDevices = (ListView) findViewById(R.id.bluetooth_other_devices);
		otherDevices.setAdapter(otherDevicesArrayAdapter);
		otherDevices.setOnItemClickListener(deviceOnClickListener);

		scan = (Button) findViewById(R.id.bluetooth_button_scan);
		scan.setOnClickListener(scanOnClickListener);

		discoverable = (Button) findViewById(R.id.bluetooth_button_discoverable);
		discoverable.setOnClickListener(discoverableOnClickListener);

		IntentFilter filter;

		filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		this.registerReceiver(receiver, filter);

		filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		this.registerReceiver(receiver, filter);

		adapter = BluetoothAdapter.getDefaultAdapter();

		pairedDevicesArrayAdapter.clear();

		Set<BluetoothDevice> devices = adapter.getBondedDevices();

		if (devices.size() > 0) {
			pairedDevicesTitle.setVisibility(View.VISIBLE);

			for (BluetoothDevice device : devices)
				pairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
		} else
			pairedDevicesTitle.setVisibility(View.GONE);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (adapter.isDiscovering())
			adapter.cancelDiscovery();

		unregisterReceiver(receiver);
	}
}